//
//  @ Project : tp1-algo3
//  @ File Name : Motor.java
//  @ Date : 04/05/2008
//  @ Author : Claudia, Jorge, Luciana, Luciano
//
package modelo.auto;

import modelo.excepciones.*;


public class Motor extends Componente {

	private static final long serialVersionUID = 1L;
	// Constantes
	public static final double DEFAULT_MAX_VEL 			= 220.0; 	// Velocidad por default de un nuevo motor
	public static final double DEFAULT_MAX_RPM 			= 60000.0; 	// RPMs por default de un nuevo motor
    public static final int DEFAULT_MAX_MARCHAS_ALLOWED = 6;		// Maximo de marchas por default de un nuevo motor
	public static final double DEFAULT_OFFSET_RPM 		= 500.0; 	// Incremento por default de las RPM al acelerar
																	// el motor en la primera marcha.
	private static final int DEFAULT_PESO 				= 500;
	
	private static final int TIEMPO_DESACELERACION 		= 8000;		// Tiempo de desaceleracion del las RPM, en milisegundos.
	
	// Propiedades fisicas
	private double rpm;	
	private double maxRpm;
	private double offsetRpm;		// Incremento base de las RPM.
	
	private double velocidad;		// En HP.
	private double maxVelocidad;	// En HP.
	private double offsetVelocidad;	// En HP. Incremento de la velocidad m�xima final en
									// cambio de marcha.
	
    private int maxMarchasAllowed;
    private int marchaAnterior;
    private Boolean acelerando;
	
	// Propiedades realitivas a sus componentes
	private Caja caja;
	
	
	// M�todos

	/**
	 * Constructor 1/1
	 * Crea un motor con valores por default.
	 * @param caja Caja a utilizar por el motor.
	 */
	public Motor(){
		super();
		
		acelerando = false;
		
		this.setDescripcion("Motor por default");
		this.setTipo("Motor".toUpperCase());
		this.setPrecio(100);
		this.setPeso(DEFAULT_PESO);
		this.caja = new Caja();
		
		// Inicializaci�n de propiedades f�sicas
		maxVelocidad = DEFAULT_MAX_VEL;		
		velocidad = 0.0;
		
		maxRpm = DEFAULT_MAX_RPM;
		offsetRpm = DEFAULT_OFFSET_RPM;
		rpm = 0.0;
		
		maxMarchasAllowed = DEFAULT_MAX_MARCHAS_ALLOWED;
		
		offsetVelocidad = maxVelocidad / maxMarchasAllowed;
		
		marchaAnterior = 0;
	}
	
	/**
	 * Constructor 2/2
	 * Crea un motor a partir de valores pasados por parametro.
	 */
	public Motor(String descripcion, String tipo, double costo, double peso, double factVel, double factAcel, double vidaUtil, double rpm, double maxVelocidad){
		super();
		
		acelerando = false;
		
		this.setDescripcion(descripcion);
		this.setTipo(tipo.toUpperCase());
		this.setPrecio(costo);
		this.setPeso(peso);
		this.caja = new Caja();
		this.setFactorVelocidad(factVel);
		this.setFactorAceleracion(factAcel);
		this.setVidaUtil(vidaUtil);
		
		// Inicializaci�n de propiedades f�sicas
		this.maxVelocidad = maxVelocidad;		
		velocidad = 0.0;
		
		maxRpm = rpm;
		offsetRpm = DEFAULT_OFFSET_RPM;
		this.rpm = 0.0;
		
		maxMarchasAllowed = this.caja.getMaxMarcha();
		
		offsetVelocidad = this.maxVelocidad / maxMarchasAllowed;
		
		marchaAnterior = 0;
	}
	
	/**
	 * Actualizaci�n del estado del motor
	 * @param elapsed Tiempo pasado en milisegundos desde la ultima actualizaci�n.
	 */
	public void update(float elapsed) {	
		// En caso de que se haya pasado a una marcha superior...
		if(marchaAnterior < caja.getMarcha()) {
			rpm *= 0.1;
		}
		marchaAnterior = caja.getMarcha();
		
		
		if(acelerando) {
			if(caja.getMarcha() > 0) {
				velocidad = (rpm / maxRpm) * offsetVelocidad + offsetVelocidad * (caja.getMarcha() -1);
				acelerando = false;
			}
		}
		else {
			rpm -= elapsed * maxRpm / TIEMPO_DESACELERACION;
			//System.out.println(rpm);
			if(rpm < 0.0) rpm = 0.0;
		}
	}
	
	/**
	 * Aceleraci�n del motor. Repercute en la velocidad.
	 */
	public void acelerar(double FactAcelTot) {
		if(rpm < maxRpm) {
			Double increment = (caja.getMarcha() > 0)? offsetRpm / caja.getMarcha() : offsetRpm;
			rpm += increment * FactAcelTot;
			
			acelerando = true;
		}
	}
	
	// Getters y Setters

	/**
	 * Devuelve la velocidad actual alcanzada por el motor.
	 */
	public double getVelocidad() {
		return velocidad;
	}	
	
	/**
	 * Devuelve las revoluciones por minuto actuales del motor.
	 */
	public double getRPM() { 
		return this.rpm;
	}	
	
	public void setRPM(Double rpm) { 
		this.rpm = rpm;
	}
	
	/**
	 * Asigna el incremento base de las RPM al acelerar un motor en primera.
	 * En base a este n�mero, se calcula el incremento de las RPM en el resto
	 * de las marchas.
	 */
	public void setRPMOffset(Double offsetRpm) { 
		this.offsetRpm = offsetRpm;
	}
	
	/**
	 * Asigna la velocidad m�xima del motor.
	 * @param maxVelocidad Velocidad m�xima que podra alcanzar el motor.
	 */
	public void setMaxVelocidad(double maxVelocidad) {
		this.maxVelocidad = maxVelocidad;
		offsetVelocidad = maxVelocidad / maxMarchasAllowed;
	}
	
	public double getMaxVelocidad(){	
		return this.maxVelocidad;
	}
	
	
	/**
	 * Asigna la cantidad de revoluciones por minuto (RPM) m�ximas del motor.
	 * @param maxRpm RPMs m�ximas que puede alcanzar el motor.
	 */
	public void setMaxRPM(double maxRpm){	
		this.maxRpm = maxRpm;
	}
	
	public double getMaxRPM(){
		return this.maxRpm;
	}	
	
	/**
	 * Asigna una Caja al motor. Si al motor se le es asignada una caja con 
	 * el maximo de marchas permitidas por el motor, mayor ser� la velocidad
	 * aprovechada en este.
	 * @param caja Referencia a una caja.
	 * @throws InvalidMaxMarchaCajaException Excepci�n lanzada en caso de
	 * que se asigne una caja con mayores velocidades que las soportadas por
	 * el motor.
	 */
	public void setCaja(Caja caja) throws InvalidMaxMarchaCajaException{
		if(caja.getMaxMarcha() > maxMarchasAllowed) {
			throw new InvalidMaxMarchaCajaException();
		}
		else {
			this.caja = caja;
		}
	}
	public Caja getCaja() {
		return this.caja;
	}	
	
	public void setVelocidad(double vel){
		this.velocidad = vel;
	}
	
	
}
